package com.github.chirspan.xaas.mybatis.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.chirspan.xaas.mybatis.annotation.DeleteOption;
import com.github.chirspan.xaas.mybatis.model.BaseModel;
import com.github.chirspan.xaas.mybatis.service.IBaseService;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

/**
 * ************************
 * <p></p>
 * *************************
 *
 * @author chenpan
 * @date 2021/1/19 10:07
 */
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseModel> extends ServiceImpl<M, T> implements IBaseService<T> {

    @Override
    public IPage pageList(Page<T> page, QueryWrapper wrapper) {
        return super.page(page, wrapper);
    }

    /**
     * 获取全部数据
     *
     * @return
     */
    @Override
    public List<T> selectAll() {
        return super.list();
    }

    /**
     * 获取总数量
     *
     * @param entity
     * @return
     */
    @Override
    public int count(T entity) {
        return super.count(Wrappers.query(entity));
    }

    /**
     * 获取满足条件的数量
     *
     * @param wrapper
     * @return
     */
    @Override
    public int count(QueryWrapper wrapper) {
        return super.count(wrapper);
    }

    /**
     * 根据主键Id获取数据
     *
     * @param id
     * @return
     */
    @Override
    public T selectById(String id) {
        return super.getById(id);
    }

    /**
     * 保存对象
     *
     * @param entity
     * @return
     */
    @Override
    public boolean add(T entity) {
        return save(entity);
    }

    /**
     * 根据主键id删除
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(String id) {
        Class<T> clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        if (clazz.isAnnotationPresent(DeleteOption.class)) {
            DeleteOption option = clazz.getAnnotation(DeleteOption.class);
            if (option.deleteRelation() && StrUtil.isNotEmpty(option.relationField())) {
                QueryWrapper queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(option.relationField(), id);
                BaseMapper relationMapper = (BaseMapper) SpringUtil.getBean(option.relationMapper());
                relationMapper.delete(queryWrapper);
            }
        }
        return super.removeById(id);
    }

    /**
     * 根据主键批量删除
     *
     * @param list
     * @return
     */
    @Override
    public boolean batchDelete(List<String> list) {
        return super.removeByIds(list);
    }

    /**
     * 根据主键更新所有字段
     *
     * @param entity
     * @return
     */
    @Override
    public boolean updateAll(T entity) {
        return super.updateById(entity);
    }

    /**
     * 根据主键更新所有不为空字段
     *
     * @param entity
     * @return
     */
    @Override
    public boolean updateNotNull(T entity) {
        UpdateWrapper updateWrapper = new UpdateWrapper<T>();
        updateWrapper.eq("id", entity.getId());
        return super.update(entity, updateWrapper);
    }

    /**
     * 条件查询
     *
     * @param wrapper
     * @return
     */
    @Override
    public List<T> selectByWrapper(QueryWrapper wrapper) {
        return super.list(wrapper);
    }

    /**
     * 根据ID串批量查询
     *
     * @param ids
     * @return
     */
    @Override
    public List<T> selectByIds(List<String> ids) {
        return super.listByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recursiveDelete(String id) {
        List<String> idList = new ArrayList<>();
        recursiveSelectChild(id, idList);
        idList.add(id);
        idList.forEach(this::delete);
    }

    private void recursiveSelectChild(String id, List<String> idList) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        wrapper.select("id");
        List<T> childIdList = baseMapper.selectList(wrapper);
        childIdList.forEach(item -> {
            //封装idList里面
            idList.add(item.getId());
            //递归查询
            this.recursiveSelectChild(item.getId(), idList);
        });
    }
}
